﻿using RotovapPlatform.Domain.Equipment.Device.TCU.Dto;
using RotovapPlatform.Domain.Equipment.Interfaces.Base;
using RotovapPlatform.Domain.Equipment.Interfaces.Communication;
using RotovapPlatform.Domain.Common.Exceptions;
using Microsoft.Extensions.Logging;
using RotovapPlatform.Domain.Common;

namespace RotovapPlatform.Infrastructure.Equipment.Devices.TCU
{
	public class TCUDrive : ITCUBase
	{
		private readonly ISerialServerManager _serverManager;
		private readonly ILogger<TCUDrive> _logger;
		private readonly int _port;
		private readonly byte _slaveId;

		public TCUDrive(
			ISerialServerManager serverManager,
			int port,
			byte slaveId,
			string name,
			ILogger<TCUDrive> logger)
		{
			_serverManager = serverManager;
			_port = port;
			_slaveId = slaveId;
			_logger = logger;
			Name = name;
			EquipmentId = $"TCU_{port}_{slaveId}";
		}

		public string Name { get; }
		public string EquipmentId { get; }

		public async Task<TCUStatus> GetTCUStatusAsync()
		{
			try
			{
				var registers = await _serverManager.ReadHoldingRegistersAsync(
					_port,
					_slaveId,
					0x0002,  // 起始地址 0x0002
					15       // 读取长度 (0x0010 - 0x0002 + 1)
				);

				// 获取报警字节
				ushort alarmByte = registers[0];

				// 解析各个报警位
				bool temperatureAbnormal = (alarmByte & 0x0001) != 0;  // 0x0002.0 温度异常
				bool overTemperature = (alarmByte & 0x0002) != 0;      // 0x0002.1 超温报警
				bool underTemperature = (alarmByte & 0x0004) != 0;     // 0x0002.2 欠温报警
				bool sin1Alarm = (alarmByte & 0x0008) != 0;           // 0x0002.3 SIN1报警
				bool sin2Alarm = (alarmByte & 0x0010) != 0;           // 0x0002.4 SIN2报警
																	  // 0x0002.5-7 是输出状态，不计入报警

				// 只有实际报警位才计入错误状态
				bool hasError = temperatureAbnormal || overTemperature ||
							   underTemperature || sin1Alarm || sin2Alarm;

				var status = new TCUStatus
				{
					MainTemperature = registers[3] / 100.0,  // 0x0005 对应 registers[3]
					SubTemperature = registers[4] / 100.0,   // 0x0006 对应 registers[4]
					RunTime = registers[5],                 // 0x0007 对应 registers[5]
					SetTemperature = registers[8] / 100.0,   // 0x000A 对应 registers[8]
					PowerSwitch = registers[10] == 1,       // 0x000C 对应 registers[10]
					CirculationSwitch = registers[11] == 1, // 0x000D 对应 registers[11]
					AllowCoolingSwitch = registers[12] == 1,// 0x000E 对应 registers[12]
					Error = hasError  // 只有实际报警才算作错误
				};

				if (hasError)
				{
					_logger.LogWarning("TCU {Name} 存在报警: 温度异常:{TempAbnormal}, 超温:{OverTemp}, 欠温:{UnderTemp}, SIN1:{Sin1}, SIN2:{Sin2}",
						Name, temperatureAbnormal, overTemperature, underTemperature, sin1Alarm, sin2Alarm);
				}

				return status;
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "读取TCU {Name} 状态失败", Name);
				throw new CommunicationException($"读取TCU状态失败: {ex.Message}", ex);
			}
		}

		public async Task<OperationResult> PowerSwitchAsync(bool isOn)
		{
			try
			{
				await _serverManager.WriteHoldingRegistersAsync(
					_port,
					_slaveId,
					0x000C,
					new[] { (ushort)(isOn ? 1 : 0) }
				);
				_logger.LogInformation("TCU {Name} 电源开关切换为: {State}", Name, isOn ? "开启" : "关闭");
				return OperationResult.Ok($"TCU {Name} 电源{(isOn ? "开启" : "关闭")}成功");
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "控制TCU {Name} 电源失败", Name);
				return OperationResult.Fail($"控制TCU电源失败: {ex.Message}");
			}
		}

		public async Task<OperationResult> SetTemperatureAsync(double temperature)
		{
			try
			{
				var value = (ushort)(temperature * 100);
				await _serverManager.WriteHoldingRegistersAsync(
					_port,
					_slaveId,
					0x000A,
					new[] { value }
				);
				_logger.LogInformation("TCU {Name} 设置温度为: {Temperature}℃", Name, temperature);
				return OperationResult.Ok($"TCU {Name} 温度设置为 {temperature}℃");
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "设置TCU {Name} 温度失败, 目标温度: {Temperature}℃", Name, temperature);
				return OperationResult.Fail($"设置TCU温度失败: {ex.Message}");
			}
		}

		public async Task<OperationResult> CirculationSwitchAsync(bool isOn)
		{
			try
			{
				await _serverManager.WriteHoldingRegistersAsync(
					_port,
					_slaveId,
					0x000D,
					new[] { (ushort)(isOn ? 1 : 0) }
				);
				_logger.LogInformation("TCU {Name} 循环开关切换为: {State}", Name, isOn ? "开启" : "关闭");
				return OperationResult.Ok($"TCU {Name} 循环{(isOn ? "开启" : "关闭")}成功");
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "控制TCU {Name} 循环失败", Name);
				return OperationResult.Fail($"控制TCU循环失败: {ex.Message}");
			}
		}

		public async Task<OperationResult> AllowCoolingSwitchAsync(bool isOn)
		{
			try
			{
				await _serverManager.WriteHoldingRegistersAsync(
					_port,
					_slaveId,
					0x000E,
					new[] { (ushort)(isOn ? 1 : 0) }
				);
				_logger.LogInformation("TCU {Name} 制冷开关切换为: {State}", Name, isOn ? "开启" : "关闭");
				return OperationResult.Ok($"TCU {Name} 制冷{(isOn ? "开启" : "关闭")}成功");
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "控制TCU {Name} 制冷失败", Name);
				return OperationResult.Fail($"控制TCU制冷失败: {ex.Message}");
			}
		}
	}
}